home *** CD-ROM | disk | FTP | other *** search
- Subject: v06i025: "rm" and "unrm" programs (unrm.rm)
- Newsgroups: mod.sources
- Approved: rs@mirror.UUCP
-
- Submitted by: Dave Taylor <pyramid!hplabs!hpldat!taylor>
- Mod.sources: Volume 6, Issue 25
- Archive-name: unrm.rm
-
- [ I wrote a brief manpage and a Makefile; I hope Dave forgives
- the (humorous) editorial comment in the latter. Some sites
- will want to change the "LOGNAME" strings to "USER" or similar,
- in the code below. --r$]
-
- The following `shar' file contains two programs that, when installed, will
- allow you to use "rm" as usual but also have the ability to change your
- mind and use "unrm".
-
- Another useful program from....
-
- -- Dave Taylor
-
- taylor/HP1900/UX, taylor@HPLABS.{CSNET, ARPA} or ..hplabs!taylor
-
-
- --------------------CUT HERE--------------------
- #!/bin/sh
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- # Contents: rm.c unrm.1 unrm.c Makefile
-
- echo x - rm.c
- sed 's/^XX//' > "rm.c" <<'@//E*O*F rm.c//'
- XX/** rm.c **/
-
- XX/** This program replaces 'rm' (it's assumed that this program is BEFORE
- XX /bin/rm in the path) and will ferret away copies of the files being
- XX removed to the directory /tmp/rm/<login>. Files that are copied into
- XX /tmp/rm/* can be recalled by 'unrm filename'. Every so often (probably
- XX midnight every night) a daemon should clear out the old files in the
- XX /tmp/rm directory...
-
- XX (C) Copyright 1986, Dave Taylor, Hewlett-Packard Company
- XX**/
-
- XX#include <stdio.h>
- XX#include <errno.h>
-
- XX#define real_rm "/bin/rm"
- XX#define RM_DIR "/tmp/rm"
-
- XX#define ACCESS_MODE 04 & 02
- XX#define DIR_ACCESS 04 & 01
-
- XX#define SLEN 80
-
- XX#define USERS_NAME "LOGNAME" /* "USER" in BSD */
-
- XXextern int errno;
-
- XXchar *basename(), *getlogin(), *getenv();
-
- XXmain(argc, argv)
- XXint argc;
- XXchar **argv;
- XX{
- XX extern int optind; /* for getopt */
- XX char buffer[SLEN], login_name[SLEN], dirname[SLEN], *cp;
- XX int c, oldumask;
-
- XX while ((c = getopt(argc, argv, "rfi")) != EOF) {
- XX switch (c) {
- XX case 'r' :
- XX case 'f' :
- XX case 'i' : break; /* just accept 'em... */
- XX case '?' : exit(fprintf(stderr,"Usage: rm [-rfi] files\n"));
- XX }
- XX }
-
- XX if (strlen(argv[optind]) == 0)
- XX exit(0);
-
- XX /* is the top level /tmp directory available??? */
-
- XX if (access(RM_DIR, DIR_ACCESS)) {
- XX sprintf(buffer,"mkdir %s; chmod 777 %s", RM_DIR, RM_DIR);
- XX if (system(buffer) != 0) {
- XX printf("'%s' failed!!\n", buffer);
- XX exit(1);
- XX }
- XX }
-
- XX /* now get the users login name... */
-
- XX if ((cp = getenv(USERS_NAME)) == NULL)
- XX strcpy(login_name, getlogin());
- XX else
- XX strcpy(login_name, cp);
-
- XX /* let's see if THAT directory is hangin' around... */
-
- XX sprintf(dirname, "%s/%s", RM_DIR, login_name);
-
- XX if (access(dirname, DIR_ACCESS)) {
- XX sprintf(buffer,"mkdir %s; chmod 700 %s", dirname, dirname);
- XX if (system(buffer) != 0) {
- XX printf("'%s' failed!!\n", buffer);
- XX exit(1);
- XX }
- XX }
-
- XX oldumask = umask(077);
- XX while (strlen(argv[optind]) > 0) {
- XX if (access(basename(argv[optind]), ACCESS_MODE) == 0)
- XX save_copy_of(dirname, argv[optind]);
- XX optind++;
- XX }
- XX (void) umask(oldumask);
-
- XX execv(real_rm, argv);
- XX
- XX fprintf(stderr,"rm: error %d exec'ing!\n", errno);
- XX}
-
- XXchar *basename(string)
- XXchar *string;
- XX{
- XX /** returns the basename of the file specified in string **/
-
- XX static char *buff;
-
- XX buff = string + strlen(string); /* start at last char */
- XX
- XX while (*buff != '/' && buff > string) buff--;
-
- XX return( (char *) (*buff == '/'? ++buff : buff));
- XX}
-
- XXsave_copy_of(dirname, filename)
- XXchar *dirname, *filename;
- XX{
- XX /** Try to link filename to dirname, if that fails, copy it
- XX bit by bit... **/
-
- XX char newfname[80];
-
- XX sprintf(newfname,"%s/%s", dirname, basename(filename));
-
- XX (void) unlink(newfname); /* blow it away if already there! */
-
- XX if (link(filename, newfname) != 0) {
- XX FILE *infile, *outfile;
- XX int c;
- XX
- XX if ((infile = fopen(filename, "r")) == NULL)
- XX exit(fprintf(stderr, "rm: can't read file '%s' to save a copy!\n",
- XX filename));
-
- XX if ((outfile = fopen(newfname, "w")) == NULL)
- XX exit(fprintf(stderr, "rm: can't write to file '%s'!\n",
- XX newfname));
-
- XX while ((c = getc(infile)) != EOF)
- XX putc(c, outfile);
- XX
- XX fclose(infile);
- XX fclose(outfile);
- XX }
- XX}
- @//E*O*F rm.c//
- chmod u=rw,g=r,o=r rm.c
-
- echo x - unrm.1
- sed 's/^XX//' > "unrm.1" <<'@//E*O*F unrm.1//'
- XX.TH UNRM 1 LOCAL
- XX.SH NAME
- XXunrm, rm \- remove files and bring them back
- XX.SH SYNOPSIS
- XX.B unrm
- XX[
- XX.B \-f
- XX] file ...
- XX.br
- XX.B rm
- XXfile ...
- XX.SH DESCRIPTION
- XX.I Rm
- XXis a local replacement for the standard
- XX.IR rm (1)
- XXcommand. Prior to removing a file it ferrets away a copy of it in
- XXthe directory
- XX.RI /tmp/rm/ login_id ,
- XXcreating each component along the way as necessary.
- XXThe standard ``\-r,'' ``\-f,'' and ``\-i'' options may be specified,
- XXbut they are ignored.
- XX.PP
- XXFiles that have been deleted with this version of
- XX.I rm
- XXcan than be retrieved with the
- XX.I unrm
- XXcommand.
- XX.I Unrm
- XXchecks to see that you are indeed the owner of a file before you
- XXcan copy it. It will not overwrite a file of the same name in the
- XXcurrent directory, unless the ``\-f'' flag is specified, which
- XXcauses the file to be replaced regardless.
- XX.PP
- XXIf these programs are available, the system administror will probably want
- XXto add a line like the following to /usr/lib/crontab:
- XX.RS
- XX40 4 * * * find /tmp -mtime +2 -exec rm -f {} ;
- XX.RE
- XXThis removes all files from temp that haven't been touched within
- XXtwo days.
- XX.SH BUGS
- XXStrange things can happen if you try to specify something other than
- XXa regular file.
- @//E*O*F unrm.1//
- chmod u=rw,g=rw,o=rw unrm.1
-
- echo x - unrm.c
- sed 's/^XX//' > "unrm.c" <<'@//E*O*F unrm.c//'
- XX/** unrm.c **/
-
- XX/** This is the companion program to the rm.c program, and will extract
- XX files from the RM_DIR/login directory if they exist. It checks to see
- XX that you are indeed the owner of the file before it'll let you copy
- XX it AND it ensures that the file doesn't already exist in the current
- XX directory (makes sense, eh?).
-
- XX This will not allow unrm'ing files that aren't owned by you, nor
- XX will it allow restores that replace a file of the same name in the
- XX current directory (unless '-f' is specified, which will cause the
- XX file to be replaced regardless).
-
- XX (C) Copyright 1986, Dave Taylor, Hewlett-Packard
- XX**/
-
- XX#include <stdio.h>
- XX#include <errno.h>
- XX#include <sys/types.h>
- XX#include <sys/stat.h>
-
- XX#define RM_DIR "/tmp/rm"
-
- XX/** access modes for calls to 'access()' **/
-
- XX#define DIRACCESS 02 & 04
- XX#define TOCOPY 04
- XX#define TOREPLACE 02 & 04
-
- XX#define SLEN 80
-
- XXint force_overwrite = 0; /* replace current regardless! */
-
- XXchar *getenv(), *getlogin();
-
- XXmain(argc, argv)
- XXint argc;
- XXchar **argv;
- XX{
- XX extern int optind; /* for getopt */
- XX char buffer[SLEN], login_name[SLEN], dirname[SLEN], *cp;
- XX int c;
-
- XX while ((c = getopt(argc, argv, "f")) != EOF) {
- XX switch (c) {
- XX case 'f' : force_overwrite++; break;
- XX case '?' : exit(fprintf(stderr,"Usage: unrm [-f] files\n"));
- XX }
- XX }
-
- XX if (argv[optind] == 0 || strlen(argv[optind]) == 0)
- XX exit(0);
-
- XX if (access(RM_DIR, DIRACCESS)) {
- XX fprintf(stderr,"Error: Directory %s doesn't exist!\n", RM_DIR);
- XX exit(0);
- XX }
-
- XX if ((cp = getenv("LOGNAME")) == NULL)
- XX strcpy(login_name, getlogin());
- XX else
- XX strcpy(login_name, cp);
-
- XX sprintf(dirname, "%s/%s", RM_DIR, login_name);
-
- XX if (access(dirname, DIRACCESS)) {
- XX fprintf(stderr,"Error: Directory %s doesn't exist!\n", dirname);
- XX exit(0);
- XX }
-
-
- XX while (argv[optind] && strlen(argv[optind]) > 0) {
- XX restore(dirname, argv[optind]);
- XX optind++;
- XX }
-
- XX exit(0);
- XX}
-
- XXrestore(directory, filename)
- XXchar *directory, *filename;
- XX{
- XX /** Try to link RM_DIR/filename to current directory. If that
- XX fails, try to copy it byte by byte... **/
-
- XX struct stat buffer;
- XX char newfname[80], answer[80];
-
- XX sprintf(newfname,"%s/%s", directory, filename);
-
- XX if (access(newfname,TOCOPY) != 0)
- XX return(fprintf(stderr,"Error: Can't find old copy of '%s'!\n",
- XX filename));
- XX
- XX if (stat(newfname, &buffer) != 0)
- XX return(fprintf(stderr,"Error: Can't stat old copy of '%s'!\n",
- XX filename));
-
- XX if (buffer.st_uid != getuid())
- XX return(fprintf(stderr,"Error: File '%s' isn't yours to restore!\n",
- XX filename));
-
- XX /** now we're ready to start some REAL work... **/
-
- XX if (access(filename,TOREPLACE) == 0) { /* it exists! */
- XX if (! force_overwrite)
- XX printf(
- XX "File %s already exists in this directory! Replace it? (y/n) ",
- XX filename);
- XX gets(answer, 1);
- XX if (tolower(answer[0]) != 'y') {
- XX fprintf(stderr,"Restore of file %s cancelled\n", filename);
- XX return;
- XX }
- XX }
-
- XX (void) unlink(filename); /* blow it away, if it's here! */
-
- XX if (link(newfname, filename) != 0) {
- XX FILE *infile, *outfile;
- XX int c;
- XX
- XX if ((infile = fopen(newfname, "r")) == NULL)
- XX exit(fprintf(stderr,
- XX "Error: Can't read file '%s' to restore from!\n",
- XX newfname));
-
- XX if ((outfile = fopen(filename, "w")) == NULL)
- XX exit(fprintf(stderr, "Error: Can't write to file '%s'!\n",
- XX filename));
-
- XX while ((c = getc(infile)) != EOF)
- XX putc(c, outfile);
- XX
- XX fclose(infile);
- XX fclose(outfile);
- XX }
-
- XX unlink(newfname);
-
- XX fprintf(stderr,"Restored file '%s'\n", filename);
- XX}
- @//E*O*F unrm.c//
- chmod u=rw,g=r,o=r unrm.c
-
- echo x - Makefile
- sed 's/^XX//' > "Makefile" <<'@//E*O*F Makefile//'
-
- XXall: unrm rm
-
- XXunrm: unrm.c ; cc $(CFLAGS) -o $@ $?
- XXrm: rm.c ; cc $(CFLAGS) -o $@ $?
- XXinstall:
- XX @echo surely you jest
- @//E*O*F Makefile//
- chmod u=rw,g=rw,o=rw Makefile
-
- echo Inspecting for damage in transit...
- temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
- trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
- cat > $temp <<\!!!
- 136 428 3194 rm.c
- 43 221 1170 unrm.1
- 142 454 3554 unrm.c
- 7 24 117 Makefile
- 328 1127 8035 total
- !!!
- wc rm.c unrm.1 unrm.c Makefile | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
- if test -s $dtemp
- then echo "Ouch [diff of wc output]:" ; cat $dtemp
- else echo "No problems found."
- fi
- exit 0
-